import os
import sys
import re
import shutil
import time

import mechanize
from BeautifulSoup import BeautifulSoup
import cookielib
from PyQt4 import QtCore, QtGui, Qt

from ScopusRetrieval import Ui_ScopusRetrMainWindow
from prefs_dialog import Ui_PreferencesDialog
from indexing_dialog import Ui_IndexingDialog
import reference_retrieve
import pdf_downloader
import common_tools

class StartQT4(QtGui.QMainWindow):
    '''
    The main run class.
    '''
    def __init__(self, parent=None):
        '''
        The main run file.
        1. Setup the window
        2. Size the windows correctly
        3. Initialize some variables for later use
        4. Initialize thread variables
        5. Make a new timer, start it and connect it to the download pool.
        6. Connections of different widgets and actions
        7. Add a clipboard to keep track of clipped functions.
        8. Read the configuration file to get configuration values for this session.
        9. check proxy and scopus settings.
        10. Create and maintain a progress dialog
        '''

        #1. Window setup
        QtGui.QWidget.__init__(self, parent)
        self.ui = Ui_ScopusRetrMainWindow()
        self.ui.setupUi(self)
        self.ui.mainTab.setTabsClosable(True)
        self.ui.ObtainFTextButton.setText("Obtain Searchable Text (and pdfs)")
        self.ui.scopusSearchLabel.setText("Search string (keyword, a: for author, j: for journal, y: for beginYear-endYear) e.g. 'neuron a:Wilson,M y:1990-2008 j:Neuroscience' without the quotes.")
        splash_pix = QtGui.QPixmap('icons/Cctrl_cc.png')
        splash = QtGui.QSplashScreen(splash_pix, QtCore.Qt.WindowStaysOnTopHint)
        splash.setMask(splash_pix.mask())
        splash.show()
        #2. Appropriate sizing when maximizing
        self.treeWidgetSized(self.ui.treeWidget)
        #3. Variables are initialized
        self.resultSet = []
        self.number_of_threads = 5
        splash.showMessage("Initializing variables")
        # For new tabs
        self.tabCount = 1
        self.hlayoutCount = 1
        self.treeCount = 1
        # For previously downloaded stuff
        self.available_texts = []
        #8.
        self.config_dict = {}
        splash.showMessage("Reading configuration files")
        self.populate_configuration('../CitationControl.conf', self.config_dict)
        configText = open('../CitationControl.conf').readlines()
        try:
            x = open('adt').read()
            x = x[1:-1]
            import bz2
            x = bz2.decompress(x)
            self.config_dict['password'] = x
        except:
            self.config_dict['password'] = ''
        configText = [x for x in configText if not x.startswith('#')]
        for i in configText:
            if not i.strip() == '':
                vals = i.split()
                header = vals[0].strip(); value = vals[1].strip()
                self.config_dict[header] = value
        self.make_icons()       
        #4. Initializing thread variables.
        self.threadCount = 0
        self.threadpool = {}
        self.pdf_download_pool = []
        self.current_pdf_threads = []
        self.done_threads = 0
        self.started_threads = 0
        self.threads_done = True

        #5. Timer setup
        self.timer = QtCore.QTimer()
        self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.timedDownload)
        self.timer.start(1000)
        
        #6. Connections
        # tree widget specific
        self.connect(self.ui.mainTab, QtCore.SIGNAL('tabCloseRequested (int)'),
                     self.tabClosed)
        # Actions
        # File menu
        self.openRecordsAction = QtGui.QAction(
            QtGui.QIcon('%sfile.png' % self.config_dict['iconLocation']),
            '&Open saved records', self)
        self.connect(self.openRecordsAction, QtCore.SIGNAL('triggered()'),
                     self.get_downloaded_file_info)
        self.ui.menuFile.addAction(self.openRecordsAction)

        self.indexRecordsAction = QtGui.QAction(
            QtGui.QIcon('%sfile.png' % self.config_dict['iconLocation']),
            '&Index local pdfs', self)
        self.connect(self.indexRecordsAction, QtCore.SIGNAL('triggered()'),
                     self.index_local_pdfs)
        self.ui.menuFile.addAction(self.indexRecordsAction)
        
        self.exitAction = QtGui.QAction(QtGui.QIcon('%sexit.png' % self.config_dict['iconLocation']),
                                                    '&Quit', self)
        self.connect(self.exitAction, QtCore.SIGNAL('triggered()'),
                     self.close)
        self.ui.menuFile.addAction(self.exitAction)

        #Edit Menu
        self.menuSeparator2 = QtGui.QAction(None)
        self.menuSeparator2.setSeparator(True)
        self.menuSeparator1 = QtGui.QAction(None)
        self.menuSeparator1.setSeparator(True)
        self.menuSeparator3 = QtGui.QAction(None)
        self.menuSeparator3.setSeparator(True)
        
        self.tagAction = QtGui.QAction(
            QtGui.QIcon('%stag.png' % self.config_dict['iconLocation']),
            '&Tag Selection(s)', self)
        self.connect(self.tagAction,
                     QtCore.SIGNAL('triggered()'), self.tag_selection)
        self.ui.menuEdit.addAction(self.tagAction)
        self.removeTagAction = QtGui.QAction(
            QtGui.QIcon('%stag.png' % self.config_dict['iconLocation']),
            '&Remove Tag(s)', self)
        self.connect(self.removeTagAction,
                     QtCore.SIGNAL('triggered()'), self.remove_tags)
        self.ui.menuEdit.addAction(self.removeTagAction)
        self.editTagAction = QtGui.QAction(
            QtGui.QIcon('%stag.png' % self.config_dict['iconLocation']),
            '&Edit Tag(s)', self)
        self.connect(self.editTagAction,
                     QtCore.SIGNAL('triggered()'), self.edit_tags)
        self.ui.menuEdit.addAction(self.editTagAction)
        self.ui.menuEdit.addSeparator()
        
        
        self.addToClipboard = QtGui.QAction(
            QtGui.QIcon('%sadd_to_clipboard.png' % self.config_dict['iconLocation']),
            '&Add to session clipboard', self)
        self.showClipboard = QtGui.QAction(QtGui.QIcon('%sshow_clipboard.png' % self.config_dict['iconLocation']),
                                          '&Show clipboard', self)
        self.clearClipboard = QtGui.QAction(QtGui.QIcon('%sclear_clipboard.png' % self.config_dict['iconLocation']),
                                          '&Clear clipboard', self)
        self.connect(self.addToClipboard,
                     QtCore.SIGNAL('triggered()'), self.add_to_clipboard)
        self.connect(self.showClipboard,
                     QtCore.SIGNAL('triggered()'), self.show_clipboard)
        self.connect(self.clearClipboard,
                     QtCore.SIGNAL('triggered()'), self.clear_clipboard)
        self.ui.menuEdit.addAction(self.addToClipboard)
        self.ui.menuEdit.addAction(self.showClipboard)
        self.ui.menuEdit.addAction(self.clearClipboard)
        self.ui.menuEdit.addSeparator()
        
        self.getPdfAction = QtGui.QAction(QtGui.QIcon('%spdf.png' % self.config_dict['iconLocation']),
                                          'Add a local &pdf file', self)
        self.connect(self.getPdfAction,
                     QtCore.SIGNAL('triggered()'), self.getLocalPdfFile)
        self.ui.menuEdit.addAction(self.getPdfAction)
        self.downloadPdfAction = QtGui.QAction(QtGui.QIcon('%spdfd.png' % self.config_dict['iconLocation']),
                                          '&Get pdf file from the web', self)
        self.connect(self.downloadPdfAction,
                     QtCore.SIGNAL('triggered()'), self.downloadPdfFile)
        self.ui.menuEdit.addAction(self.downloadPdfAction)
        self.showPdfImagesAction = QtGui.QAction(QtGui.QIcon('%spdf.png' % self.config_dict['iconLocation']),
                                          'Show &images in the pdf file', self)
        self.connect(self.showPdfImagesAction,
                     QtCore.SIGNAL('triggered()'), self.extract_images)
        self.ui.menuEdit.addAction(self.showPdfImagesAction)
        self.ui.menuEdit.addSeparator()
        self.deleteStoredTextAction = QtGui.QAction(QtGui.QIcon('%strash.png' % self.config_dict['iconLocation']),
                                                    '&Delete stored selections', self)
        self.connect(self.deleteStoredTextAction,
                     QtCore.SIGNAL('triggered()'), self.deleteStoredText)
        self.ui.menuEdit.addAction(self.deleteStoredTextAction)
        self.ui.menuEdit.addSeparator()
        self.ui.menuEdit.addSeparator()        
        self.openPrefsAction = QtGui.QAction(QtGui.QIcon('%stoolbox.png' % self.config_dict['iconLocation']),
                                                    '&Open Preferences', self)
        self.connect(self.openPrefsAction,
                     QtCore.SIGNAL('triggered()'), self.open_preferences)
        self.ui.menuEdit.addAction(self.openPrefsAction)
        
        self.aboutAction = QtGui.QAction(QtGui.QIcon('%stest.png' % self.config_dict['iconLocation']),
                                                    '&About Citation Control', self)
        self.connect(self.aboutAction,
                     QtCore.SIGNAL('triggered()'), self.aboutCitationControl)
        self.ui.menuHelp.addAction(self.aboutAction)
        # Button connections
        self.connect(self.ui.ObtainCiteButton, QtCore.SIGNAL('clicked()'),
                     self.obtain_citations)
        self.connect(self.ui.ObtainRefButton, QtCore.SIGNAL('clicked()'),
                     self.obtain_references)
        self.connect(self.ui.ObtainFTextButton, QtCore.SIGNAL('clicked()'),
                     self.obtainFTextButton_clicked)
        self.connect(self.ui.scopusSearchButton, QtCore.SIGNAL('clicked()'),
                     self.search_scopus_button_clicked)
        self.connect(self.ui.scopusSearchLineEdit, QtCore.SIGNAL('returnPressed ()'),
                     self.search_scopus_button_clicked)
        self.connect(self.ui.lineEdit, QtCore.SIGNAL('returnPressed ()'),
                     self.fullTextSearch)
        self.connect(self.ui.treeWidget, QtCore.SIGNAL('itemSelectionChanged()'), self.show_selection_status)
        self.ui.treeWidget.itemDoubleClicked.connect(self.item_double_clicked)
        self.connect(self.ui.pushButton, QtCore.SIGNAL('clicked()'),
                     self.fullTextSearch)
        self.connect(self.ui.lineEdit, QtCore.SIGNAL('textChanged (const QString&)'),
                     self.fullTextSearchAuto)
        #Filters
        self.connect(self.ui.TitleFilter, QtCore.SIGNAL('textChanged (const QString&)'),
                     self.filter_title)
        self.connect(self.ui.AuthorFilter, QtCore.SIGNAL('textChanged (const QString&)'),
                     self.filter_author)
        self.connect(self.ui.YearFilter, QtCore.SIGNAL('textChanged (const QString&)'),
                     self.filter_year)
        self.connect(self.ui.JournalFilter, QtCore.SIGNAL('textChanged (const QString&)'),
                     self.filter_journal)
        self.connect(self.ui.TagFilter, QtCore.SIGNAL('textChanged (const QString&)'),
                     self.filter_tag)
        
        #Menu items
        
        
        #7.
        self.clipboard = []
        
        #9.
        splash.clearMessage()
        splash.showMessage("Checking internet connection")
        if not common_tools.isonline():
            QtGui.QMessageBox.information (self, 'Check internet connection',
                                           "Just pinged google and got no response. \
                                           Check your internet connection",
                                           QtGui.QMessageBox.Ok)
        splash.clearMessage()
        splash.showMessage("Scopus Access check and obtain id")

        scopus_searcher = pdf_downloader.ScopusSearchWidget()
        scopus_test = scopus_searcher.search_scopus('', self.config_dict, True)
        if not scopus_test:
            QtGui.QMessageBox.information (self, 'Check proxy settings',
                                           "Just tested scopus and got no response. \
                                           Check your connection. Open Edit.Preferences and change \
                                           settings.",
                                           QtGui.QMessageBox.Ok, QtGui.QMessageBox.Cancel)
        else:
            txgid_re = re.compile('txGid=(.*?)\&')
            self.config_dict['ScopusId'] = txgid_re.findall(scopus_test)[0]
            QtGui.QMessageBox.information (self, 'Success',
                                           "Just tested scopus and got an id.",
                                           QtGui.QMessageBox.Ok)
        #10.
        import progress_dialog
        self.prog_window = QtGui.QDialog(self)
        self.prog_dialog = progress_dialog.Ui_Dialog()
        self.prog_dialog.setupUi(self.prog_window)
        self.prog_window.hide()

        self.img_window = QtGui.QDialog(self)
        self.img_dialog = progress_dialog.Ui_Dialog()
        self.img_dialog.setupUi(self.img_window)
        self.img_dialog.label.setText('Extracting images from the pdf file.')
        self.img_window.hide()
        splash.hide()

    def make_icons(self):
        '''
        Make icons for different functions.
        '''
        self.done_icon = QtGui.QIcon()
        self.tabDone_icon = QtGui.QIcon()
        self.tabWorking_icon = QtGui.QIcon()
        self.error_icon = QtGui.QIcon()
        self.notDone_icon = QtGui.QIcon()
        self.working_icon = QtGui.QIcon()
        self.done_icon.addPixmap(QtGui.QPixmap("%sdone.png" % self.config_dict['iconLocation']), QtGui.QIcon.Normal, QtGui.QIcon.On)
        self.notDone_icon.addPixmap(QtGui.QPixmap("%snotDone.png" % self.config_dict['iconLocation']), QtGui.QIcon.Normal, QtGui.QIcon.On)
        self.error_icon.addPixmap(QtGui.QPixmap("%serror.png" % self.config_dict['iconLocation']), QtGui.QIcon.Normal, QtGui.QIcon.On)
        self.working_icon.addPixmap(QtGui.QPixmap("%sworking.png" % self.config_dict['iconLocation']), QtGui.QIcon.Normal, QtGui.QIcon.On)
        self.tabDone_icon.addPixmap(QtGui.QPixmap("%stabDone.png" % self.config_dict['iconLocation']), QtGui.QIcon.Normal, QtGui.QIcon.On)
        self.tabWorking_icon.addPixmap(QtGui.QPixmap("%stabWorking.png" % self.config_dict['iconLocation']), QtGui.QIcon.Normal, QtGui.QIcon.On)
                                           
    def add_data(self, lst, treeWidget, tab_location, threadnum):
        '''
        The main function that adds data into a tab. It receives the list for the tab, its treewidget and
        the tab location as arguments.
        It does the following.
        1. Adds the list to self.resultSet at the tab location if that still exists. If not, then quit.
           The only caveat here is this. If a search is started, but the tab is closed, the search is still
           done and results obtained.
        2. Add some actions to the treeWidget and
        3. load the list into the treeWidget. Remember that the first
           element in the list is just the title.
        4. Changes the color of tab header to indicate done.
        '''
        #1.
        try:
            self.resultSet[tab_location] = lst
        except:
            return
        #2. 
        treeWidget.clear()
        details_titles = ['Title',
                          'Authors', 'Year', 'Journal', 'Issue', 'Pages']
        treeWidget.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
        treeWidget.addActions([self.tagAction, self.removeTagAction, self.editTagAction, self.menuSeparator1,
                               self.addToClipboard, self.showClipboard, self.menuSeparator2,
                               self.deleteStoredTextAction, self.menuSeparator3,
                               self.getPdfAction, self.downloadPdfAction, self.showPdfImagesAction])

        #3.
        for num, cite in enumerate(lst[1:]):
            a = QtGui.QTreeWidgetItem(treeWidget)
            a.setIcon(7, self.notDone_icon)
            eid_checkval = cite['EID']
            publisher_link = cite['ArticleLink']
            cite['Tags'] = cite.get('Tags', '')
            if publisher_link:
                if publisher_link.strip() == '':
                    a.setIcon(7, self.error_icon)
            if os.path.isfile('%s%s.txt' % (self.config_dict['storageLocation'], eid_checkval)):
                a.setIcon(7, self.done_icon)
                detail = eval(open('%s%s.dxt' % (self.config_dict['storageLocation'], eid_checkval)).read())
                a.setText(6, detail['Tags'])
            for num, detail in enumerate(details_titles):
                a.setText(num, cite[detail])

        #4.
        orig_tab_text = self.ui.mainTab.tabText(tab_location)
        self.ui.mainTab.setTabIcon(tab_location, self.tabDone_icon)

    def search_scopus_button_clicked(self):
        '''
        When the scopus search button is clicked:
        1. Get the text to search, make up a waiting text
           for treewidgets and a statusbar msg_value
        2. Get the treeWidget where the final data goes into
           and the location of the tab using make_new_tab.
        3. Create a new thread for scopus search, add it to the threadpool and start it.
        
        '''
        self.ui.textEdit.clear()
        self.ui.textEdit.setHtml('Searching scopus for results.')
        #1. 
        search_text = self.ui.scopusSearchLineEdit.text()
        msg_value = 'Scopus search for %s.' % search_text
        waiting_text = "Waiting: %s." % msg_value
        #2.
        treeWidget, tabLoc = self.make_new_tab(search_text, waiting_text)
        self.ui.mainTab.setTabIcon(tabLoc, self.tabWorking_icon)
        #3.
        t = pdf_downloader.ScopusSearchThread(treeWidget, self.config_dict)
        self.threadpool[self.threadCount] = t
        self.connect(self.threadpool[self.threadCount],
                     QtCore.SIGNAL('resultsObtained'), self.add_data)
        self.connect(self.threadpool[self.threadCount],
                     QtCore.SIGNAL('startFreezeProc'), self.on_start_freeze)
        self.connect(self.threadpool[self.threadCount],
                     QtCore.SIGNAL('endFreezeProc'), self.on_end_freeze)
        self.ui.statusbar.clearMessage()
        self.ui.statusbar.showMessage(msg_value, 3000)
        self.threadpool[self.threadCount].start_process(search_text, tabLoc, self.threadCount)
        self.threadCount += 1

    def obtain_citations(self):
        '''
        Obtains citations for a selected article.
        1. Get a handle to the current tree. Also get the number of selected items.
        2. Make sure that there is only one item selected. Else, give an error message.
        3. From resultSet, get the title and scopus record of the article. This is where the number
        of citations will be given.
        4. Using a message and waiting value, make a new tab.
        5. Start a new thread for getting citations.
        '''
        #1. 
        currentTreeWidget, current_tab_index = self.getTreeWidget_index()
        selected_items = currentTreeWidget.selectedItems()

        #2. 
        if len(selected_items) == 0:
            QtGui.QMessageBox.information (self, 'No Selection',
                                           'A record needs to be selected', QtGui.QMessageBox.Ok)
            return
        if len(selected_items) > 1:
            QtGui.QMessageBox.information (self, 'No Selection',
                                           'Only one record can be selected for this process',
                                           QtGui.QMessageBox.Ok)
            return
        #3.
        selected_item = selected_items[0]
        row_index = currentTreeWidget.indexFromItem(selected_item).row()
        record_detail = self.resultSet[current_tab_index][1:][row_index]
        title = record_detail['Title']
        record_url = record_detail['ScopusRecord']
        #4.
        msg_value = "(C): %s" % (title)
        waiting_text = "Waiting: %s." % msg_value
        treeWidget, tabLoc = self.make_new_tab(msg_value, waiting_text)
        self.ui.mainTab.setTabIcon(tabLoc, self.tabWorking_icon)
        #5.
        t = pdf_downloader.CitationSearchThread(treeWidget, self.config_dict)
        self.threadpool[self.threadCount] = t
        self.connect(self.threadpool[self.threadCount],
                     QtCore.SIGNAL('resultsObtained'), self.add_data)
        self.connect(self.threadpool[self.threadCount],
                     QtCore.SIGNAL('startFreezeProc'), self.on_start_freeze)
        self.connect(self.threadpool[self.threadCount],
                     QtCore.SIGNAL('endFreezeProc'), self.on_end_freeze)        
        self.ui.statusbar.clearMessage()
        self.ui.statusbar.showMessage(waiting_text, 2000)
        self.threadpool[self.threadCount].start_process(msg_value, record_url, tabLoc, self.threadCount)
        self.threadCount += 1

    def obtain_references(self):
        currentTreeWidget, current_tab_index = self.getTreeWidget_index()
        selected_items = currentTreeWidget.selectedItems()
        if len(selected_items) == 0:
            QtGui.QMessageBox.information (self, 'No Selection',
                                           'A record needs to be selected', QtGui.QMessageBox.Ok)
            return
        if len(selected_items) > 1:
            QtGui.QMessageBox.information (self, 'No Selection',
                                           'Only one record can be selected for this process',
                                           QtGui.QMessageBox.Ok)
            return
        selected_item = selected_items[0]
        row_index = currentTreeWidget.indexFromItem(selected_item).row()
        record_detail = self.resultSet[current_tab_index][1:][row_index]
        title = record_detail['Title']
        record_url = record_detail['ScopusRecord']
        msg_value = "(R): %s" % (title)
        waiting_text = "Waiting: %s." % msg_value
        treeWidget, tabLoc = self.make_new_tab(msg_value, waiting_text)
        self.ui.mainTab.setTabIcon(tabLoc, self.tabWorking_icon)
        t = pdf_downloader.ReferenceSearchThread(treeWidget, self.config_dict)
        self.threadpool[self.threadCount] = t
        self.connect(self.threadpool[self.threadCount],
                     QtCore.SIGNAL('resultsObtained'), self.add_data)
        self.connect(self.threadpool[self.threadCount],
                     QtCore.SIGNAL('startFreezeProc'), self.on_start_freeze)
        self.connect(self.threadpool[self.threadCount],
                     QtCore.SIGNAL('endFreezeProc'), self.on_end_freeze)        
        self.ui.statusbar.clearMessage()
        self.ui.statusbar.showMessage(waiting_text, 2000)
        self.threadpool[self.threadCount].start_process(msg_value, record_url, tabLoc, self.threadCount)
        self.threadCount += 1
        
    def obtainFTextButton_clicked(self):
        # There might be many tabs and trees. It is important to get the current one
        self.update_available_texts()
        currentTreeWidget, current_tab_index = self.getTreeWidget_index()
        selected_items = currentTreeWidget.selectedItems()
        selected_indices = []
        for item in selected_items:
            selection_row = currentTreeWidget.indexFromItem(item).row()
            selected_indices += [selection_row]
            
        for i in selected_indices:
            self.change_status(i,current_tab_index, "working")
            selection_eid = self.resultSet[current_tab_index][1:][i]['EID']
            if selection_eid in self.available_texts:
                self.change_status(i, current_tab_index, "done")
                continue
            download_details = {}
            download_details['selection_row'] = i
            download_details['current tab index'] = current_tab_index
            download_details['list'] = self.resultSet[current_tab_index][1:]
            temp_pool = [[[current_tab_index], download_details]]
            self.pdf_download_pool += temp_pool

    def update_available_texts(self):
        self.available_texts = os.listdir(self.config_dict['storageLocation'])
        self.available_texts = [x[:-4] for x in self.available_texts if x.endswith('.txt')]
        
    def timedDownload(self):
        '''
        Run whenever there is a timer tick.
        If there are no threads in the pool, then do nothing.
        If there are less that the number of threads, then run these threads.
        If more, then do the first x number of threads, then the next and so on.
        '''
        if self.threads_done:
            if len(self.pdf_download_pool) == 0:
                return
            if len(self.pdf_download_pool) <= self.number_of_threads:
                temp_pdf_download_pool = [x[1] for x in self.pdf_download_pool]
                self.current_pdf_threads = temp_pdf_download_pool[:]
                self.run_pdf_downloads(self.current_pdf_threads)
                self.pdf_download_pool = []
                self.threads_done = False
            if len(self.pdf_download_pool) > self.number_of_threads:
                temp_pdf_download_pool = self.pdf_download_pool[:self.number_of_threads]
                temp_pdf_download_pool = [x[1] for x in temp_pdf_download_pool]
                self.current_pdf_threads = temp_pdf_download_pool
                self.pdf_download_pool = self.pdf_download_pool[self.number_of_threads:]
                self.run_pdf_downloads(self.current_pdf_threads)
                self.threads_done = False

    def run_pdf_downloads(self, cur_pdfs):
        if self.threads_done:
            for i in cur_pdfs:
                t = pdf_downloader.PDFDownloadThread(self.config_dict)
                self.threadpool[self.threadCount] = t
                self.connect(self.threadpool[self.threadCount],
                             QtCore.SIGNAL("updateImage"), self.change_status)
                self.connect(self.threadpool[self.threadCount],
                             QtCore.SIGNAL("done"), self.done_thread)
                self.started_threads += 1
                self.threadpool[self.threadCount].start_process(i['selection_row'],
                                                         i['current tab index'],
                                                         i['list'],
                                                         self.threadCount)
                self.threadCount += 1
                
    def done_thread(self, threadnum):
        self.done_threads += 1
        if self.done_threads == self.started_threads:
            self.started_threads = 0
            self.done_threads = 0
            self.threads_done = True
            
    def tabClosed(self, int):
        if len(self.resultSet) > 0:
            self.ui.mainTab.removeTab(int)
            self.resultSet.pop(int)
            self.pdf_download_pool = [x for x in self.pdf_download_pool if not x[0][0] == int]
            
    def add_to_clipboard(self):
        ''' Just add to a list which will be saved throughout this session.
        '''
        currentTreeWidget, current_ind = self.getTreeWidget_index()
        selected_items = currentTreeWidget.selectedItems()
        if len(selected_items) == 0: return
        for i in selected_items:
            selection_row = currentTreeWidget.indexFromItem(i).row()
            selection_record = self.resultSet[current_ind][selection_row+1]
            self.clipboard += [selection_record]

    def clear_clipboard(self):
        ''' Clear the clipboard
        '''
        self.clipboard = []
        
    def show_clipboard(self):
        '''
        Just show everything that was saved.
        '''
        self.ui.textEdit.clear()
        output = ['<b> CitationControl Clipboard: </b>']
        for i in self.clipboard:
            title = i['Title']
            authors = i['Authors']
            journal = i['Journal']
            yr = i['Year']            
            issue = i['Issue']
            pages = i['Pages']
            output_val = '%s, <i>%s</i>, <b><font color="#330000">%s</font></b>. %s; %s: %s.' % (
                authors, title, journal, yr, issue, pages)
            output += [output_val]
        clip_html = '<br><br>'.join(output)
        self.ui.textEdit.setHtml(clip_html)
        
    def fullTextSearchAuto(self):
        '''
        Automatically searches the full text when characters are entered.
        '''
        currentTreeWidget, current_ind = self.getTreeWidget_index()
        selected_items = currentTreeWidget.selectedItems()
        if len(selected_items) > 1: return
        if len(selected_items) == 0: return
        search_term = str(self.ui.lineEdit.text()).strip()
        if len(search_term.split()) > 1: return
        if not search_term == '':
            self.fullTextSearch()
        
    def fullTextSearch(self):
        search_term = str(self.ui.lineEdit.text()).strip()
        if search_term == '':
            QtGui.QMessageBox.information (self, 'No Search Term',
                                           'A search term needs to be entered', QtGui.QMessageBox.Ok)
            return
        self.ui.textEdit.clear()
        currentTreeWidget, current_ind = self.getTreeWidget_index()
        selected_items = currentTreeWidget.selectedItems()
        if len(selected_items) == 0:
            QtGui.QMessageBox.information (self, 'No Selection',
                                           'A record needs to be selected', QtGui.QMessageBox.Ok)
            return
        if len(selected_items) > 1:
            self.fulltextSearchMultiple(search_term)
            return
        selection_row = currentTreeWidget.indexFromItem(selected_items[0]).row()
        # Get the actual record offset by 1
        selection_record = self.resultSet[current_ind][selection_row+1]
        eid_of_selection = selection_record['EID']
        try:
            fulltext = open('%s%s.txt' % (self.config_dict['storageLocation'], eid_of_selection)).read()
        except:
            QtGui.QMessageBox.information (self, 'Non-existant record',
                                           'The full text has not been downloaded.', QtGui.QMessageBox.Ok)
            return
        fulltext = fulltext.split('\n')
        and_split = search_term.split(' (and) ')
        or_split = search_term.split(' (or) ')
        newText = []
        if (len(and_split) > 1) and (len(or_split) > 1):
            QtGui.QMessageBox.warning (self, 'Chained operators',
                                           'Only one "and" or "or" can be searched at this time.',
                                           QtGui.QMessageBox.Ok)
            return
        elif len(and_split) > 1:
            newText = self.return_operator_test(fulltext, and_split, 'and')
            newText = '<br><br>'.join(newText)
        elif len(or_split) > 1:
            newText = self.return_operator_test(fulltext, or_split, 'or')
            newText = '<br><br>'.join(newText)
        else:
            newText = [x for x in fulltext if str(search_term).lower() in x.lower()]
            newText = '<br><br>'.join(newText)
            strongText = '<b><font color="#330000">%s</font></b>' % search_term
            newText = newText.replace(search_term, strongText)
        if newText == '': newText = 'String "%s" absent in this article' % search_term
        self.ui.textEdit.clear()
        self.ui.textEdit.setHtml(newText)

    def return_operator_test(self, fulltxt, opArray, oper):
        '''
        A utility function to check for ands and ors.
        '''
        newText = []
        opArray = [x.lower() for x in opArray]
        opArrays = ['"%s"' % x.strip() for x in opArray]
        opArrays = (' in x.lower() %s ' % oper).join(opArrays)
        opArrays = opArrays + ' in x.lower()'
        for x in fulltxt:
            if eval(opArrays):
                for i in opArray:
                    op_val = re.compile(i, re.IGNORECASE)
                    x = op_val.sub('<b><font color="#330000">%s</font></b>' % i, x)
                newText += [x]
        return newText
            
    def fulltextSearchMultiple(self, search_term):
        self.ui.textEdit.clear()
        currentTreeWidget, current_ind = self.getTreeWidget_index()
        for i in range(currentTreeWidget.topLevelItemCount()):
            item = currentTreeWidget.topLevelItem(i)
            item.setBackgroundColor(0, QtGui.QColor(QtCore.Qt.white))
        selected_items = currentTreeWidget.selectedItems()
        # This will need to be dried.
        and_split = search_term.split(' (and) ')
        or_split = search_term.split(' (or) ')        
        for i in selected_items:
            newText = []
            currentTreeWidget.setItemSelected(i, False)
            selection_row = currentTreeWidget.indexFromItem(i).row()
            # Get the actual record offset by 1
            selection_record = self.resultSet[current_ind][selection_row+1]
            eid_of_selection = selection_record['EID']
            try:
                fulltext = open('%s%s.txt' % (self.config_dict['storageLocation'], eid_of_selection)).read()
            except:
                continue
            fulltext = fulltext.split('\n')
            if len(and_split) > 1:
                newText = self.return_operator_test(fulltext, and_split, 'and')
            elif len(or_split) > 1:
                newText = self.return_operator_test(fulltext, or_split, 'or')
            else:
                newText = [x for x in fulltext if str(search_term).lower() in x.lower()]
                
            if len(newText) > 0:
                i.setBackgroundColor(0, QtGui.QColor(QtCore.Qt.yellow))

    def make_new_tab(self, tabTitle, waitingTxt, insertAfter=None):
        if len(tabTitle) > 30: tabTitle = tabTitle[:30]
        if self.tabCount == 1:
            self.ui.mainTab.setTabText(0, tabTitle)
            self.ui.treeWidget.clear()
            treeWidget = self.ui.treeWidget
            self.tabCount += 1
        else:
            self.tabCount += 1
            self.hlayoutCount += 1
            self.treeCount += 1
            tab = QtGui.QWidget()
            tab.setObjectName("tab%s" % self.tabCount)
            hlayout = QtGui.QHBoxLayout(tab)
            hlayout.setObjectName("horizontalLayout%s" % self.hlayoutCount)
            hlayout2 = QtGui.QHBoxLayout()
            hlayout2.setContentsMargins(-1, 1, -1, -1)
            self.hlayoutCount += 1
            hlayout2.setObjectName("horizontalLayout%s" % self.hlayoutCount)
            treeWidget = QtGui.QTreeWidget(tab)
            treeWidget.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
            treeWidget.setObjectName("treeWidget%s" % self.treeCount)
            self.treeWidgetSized(treeWidget)
            self.connect(treeWidget, QtCore.SIGNAL('itemSelectionChanged()'), self.show_selection_status)
            treeWidget.itemDoubleClicked.connect(self.item_double_clicked)
            header_titles = ['Title',
                              'Authors', 'Year', 'Journal', 'Issue', 'Pages', 'Tags', 'Process']
            for num, title in enumerate(header_titles):
                treeWidget.headerItem().setText(num,
                                                QtGui.QApplication.translate(
                                                    "ScopusRetrMainWindow", title, None,
                                                    QtGui.QApplication.UnicodeUTF8))
            hlayout.addWidget(treeWidget)
            if not insertAfter:
                self.ui.mainTab.addTab(tab, tabTitle)
            else:
                self.ui.mainTab.insertTab(insertAfter, tab, tabTitle)
        tab_index_location = len(self.resultSet)
        self.resultSet += [False]
        a = QtGui.QTreeWidgetItem(treeWidget)
        a.setText(0, waitingTxt)
        return treeWidget, tab_index_location

    def getTreeWidget_index(self):
        current_ind = self.ui.mainTab.currentIndex()
        currentTreeWidget = None
        for i in self.ui.mainTab.currentWidget().children():
            if 'treeWidget' in i.objectName():
                currentTreeWidget = i
        return currentTreeWidget, current_ind
        
    def change_status(self, ind, tab_index, status):
        try:
            tree = None
            for i in self.ui.mainTab.widget(tab_index).children():
                if 'treeWidget' in i.objectName():
                    tree = i
            treeItem = tree.topLevelItem(ind)
            iconval = eval('self.%s_icon' % status)
            treeItem.setIcon(7, iconval)
        except:
            pass

    def removeThread(self, threadnum):
        self.threadpool.pop(threadnum)

    def deleteStoredText(self):
        currentTreeWidget, current_tab_index = self.getTreeWidget_index()
        selected_items = currentTreeWidget.selectedItems()
        if len(selected_items) == 0: return
        reply = QtGui.QMessageBox.question(self, 'Message',
                                           "The saved text will be deleted. Are you sure?",
                                           QtGui.QMessageBox.Yes,
                                           QtGui.QMessageBox.No)
        if not reply == QtGui.QMessageBox.Yes:
            return
        for i in selected_items:
            selection_row = currentTreeWidget.indexFromItem(i).row()
            # Get the actual record offset by 1
            selection_record = self.resultSet[current_tab_index][selection_row+1]
            eid_of_selection = selection_record['EID']
            try:
                os.remove('%s%s.dxt' % (self.config_dict['storageLocation'], eid_of_selection))
                os.remove('%s%s.txt' % (self.config_dict['storageLocation'], eid_of_selection))
                os.remove('%s%s.pdf' % (self.config_dict['storageLocation'], eid_of_selection))
            except:
                self.ui.statusbar.clearMessage()
                self.ui.statusbar.showMessage('Record for %s not found' % selection_record['Title'], 2000)
            self.change_status(selection_row,current_tab_index, "notDone")

    def tag_selection(self):
        currentTreeWidget, current_tab_index = self.getTreeWidget_index()
        selected_items = currentTreeWidget.selectedItems()
        if len(selected_items) == 0: return
        text, ok = QtGui.QInputDialog.getText(self, 'Tag Dialog', 'Enter tags for selection:')
        if ok:
            tag_name = str(text)
        else:
            return
        for i in selected_items:
            selection_row = currentTreeWidget.indexFromItem(i).row()
            selection_record = self.resultSet[current_tab_index][selection_row+1]
            eid_of_selection = selection_record['EID']
            tags = selection_record['Tags'].split(',')
            tags = [x.strip() for x in tags]
            if len(tags) == 1:
                if tags[0] == '':
                    tags = []
            tags += [tag_name]
            new_tag_name = ', '.join(tags)
            selection_record['Tags'] =  new_tag_name
            try:
                f = open('%s%s.dxt' % (self.config_dict['storageLocation'], eid_of_selection), 'w'); f.write(repr(selection_record)); f.close()
                treeItem = currentTreeWidget.topLevelItem(selection_row)
                treeItem.setText(6, new_tag_name)
            except:
                self.ui.statusbar.clearMessage()
                self.ui.statusbar.showMessage('Record for %s not found' % selection_record['Title'], 2000)

    def remove_tags(self):
        currentTreeWidget, current_tab_index = self.getTreeWidget_index()
        selected_items = currentTreeWidget.selectedItems()
        if len(selected_items) == 0: return
        reply = QtGui.QMessageBox.question(self, 'Message',
                                           "All tags in selection will be deleted. Are you sure?",
                                           QtGui.QMessageBox.Yes,
                                           QtGui.QMessageBox.No)
        if not reply == QtGui.QMessageBox.Yes:
            return
        for i in selected_items:
            selection_row = currentTreeWidget.indexFromItem(i).row()
            selection_record = self.resultSet[current_tab_index][selection_row+1]
            eid_of_selection = selection_record['EID']
            selection_record['Tags'] =  ''
            try:
                f = open('%s%s.dxt' % (self.config_dict['storageLocation'], eid_of_selection), 'w'); f.write(repr(selection_record)); f.close()
                treeItem = currentTreeWidget.topLevelItem(selection_row)
                treeItem.setText(6, '')
            except:
                self.ui.statusbar.clearMessage()
                self.ui.statusbar.showMessage('Record for %s not found' % selection_record['Title'], 2000)

    def edit_tags(self):
        currentTreeWidget, current_tab_index = self.getTreeWidget_index()
        selected_items = currentTreeWidget.selectedItems()
        if len(selected_items) == 0: return
        if len(selected_items) > 1:
            QtGui.QMessageBox.information (self, 'Multiple Selections',
                                           'Only one record can be selected for this process',
                                           QtGui.QMessageBox.Ok)
            return
        selected_items = selected_items[0]
        selection_row = currentTreeWidget.indexFromItem(selected_items).row()
        selection_record = self.resultSet[current_tab_index][selection_row+1]
        eid_of_selection = selection_record['EID']
        tags = selection_record['Tags']
        text, ok = QtGui.QInputDialog.getText(self, 'Tag Dialog', 'Saved tags for selection:',
                                              QtGui.QLineEdit.Normal, tags)
        if ok:
            tag_name = str(text)
        else:
            return
        selection_record['Tags'] =  tag_name
        try:
            f = open('%s%s.dxt' % (self.config_dict['storageLocation'], eid_of_selection), 'w'); f.write(repr(selection_record)); f.close()
            treeItem = currentTreeWidget.topLevelItem(selection_row)
            treeItem.setText(6, tag_name)
        except:
            self.ui.statusbar.clearMessage()
            self.ui.statusbar.showMessage('Record for %s not found' % selection_record['Title'], 2000)
            
    def get_downloaded_file_info(self):
        t = pdf_downloader.SavedDataThread(self.config_dict)
        self.threadpool[self.threadCount] = t
        self.connect(self.threadpool[self.threadCount],
                     QtCore.SIGNAL('obtained files'), self.update_downloaded_file_info)
        self.ui.statusbar.clearMessage()
        self.ui.statusbar.showMessage("Obtaining Previously Saved Records")
        self.threadpool[self.threadCount].start_process(self.threadCount)
        self.threadCount += 1

    def update_downloaded_file_info(self, lst_of_files, threadnum):
        treeWidget = None
        for i in range(self.ui.mainTab.count()):
            if self.ui.mainTab.tabText(i) == 'CitationControl-Saved':
                for j in self.ui.mainTab.widget(i).children():
                    if 'treeWidget' in j.objectName():
                        treeWidget = j
                        self.resultSet[i] = lst_of_files
                        self.add_data(lst_of_files, treeWidget, False, threadnum)
                        return 
        treeWidget, tabLoc = self.make_new_tab(lst_of_files[0], "Waiting for file load")
        self.add_data(lst_of_files, treeWidget, tabLoc, threadnum)
        self.ui.statusbar.clearMessage()
        self.ui.statusbar.showMessage("Obtained previously saved %s records" % (len(lst_of_files)-1))

    def show_selection_status(self):
        currentTreeWidget, current_tab_index = self.getTreeWidget_index()
        selected_items = currentTreeWidget.selectedItems()
        self.ui.statusbar.clearMessage()
        self.ui.statusbar.showMessage('Selected %s records' % len(selected_items), 5000)
        if len(selected_items) > 1: return
        if len(selected_items) == 0: return
        search_term = str(self.ui.lineEdit.text()).strip()
        if search_term == '': return
        self.fullTextSearch()

    def filter_title(self, text):
        self.text_entered(self.ui.TitleFilter, "Title", text)
    def filter_author(self, text):
        self.text_entered(self.ui.AuthorFilter, "Authors", text)
    def filter_year(self, text):
        self.text_entered(self.ui.YearFilter, "Year", text)
    def filter_journal(self, text):
        self.text_entered(self.ui.JournalFilter, "Journal", text)
    def filter_tag(self, text):
        self.text_entered(self.ui.TagFilter, "Tags", text)
            
        
    def text_entered(self, widgetName, cite_detail, text):
        '''
        Runs whenever text is entered into one of the filter boxes.
        1. Get the text for the filter
        2. Get the current tree and its location in the tabwidget
        3. In the list from resultSet, check whether this text is present. If not, hide the tree item.
        '''
        #1.
        filter_text = str(widgetName.text())
        #2.
        currentTreeWidget, current_tab_index = self.getTreeWidget_index()
        #3.
        lst_value = self.resultSet[current_tab_index]
        for num, i in enumerate(lst_value[1:]):
            tree_item = currentTreeWidget.topLevelItem(num)
            if not filter_text in i[cite_detail]:
                currentTreeWidget.setItemHidden(tree_item, True)
            else:
                currentTreeWidget.setItemHidden(tree_item, False)
        
        
    def getLocalPdfFile(self):
        currentTreeWidget, current_tab_index = self.getTreeWidget_index()
        selected_items = currentTreeWidget.selectedItems()
        if len(selected_items) == 0:
            QtGui.QMessageBox.information (self, 'No Selection',
                                           'A record needs to be selected', QtGui.QMessageBox.Ok)
            return
        if len(selected_items) > 1:
            QtGui.QMessageBox.information (self, 'Multiple Selections',
                                           'Only one record can be selected for this process',
                                           QtGui.QMessageBox.Ok)
            return
        selected_item = selected_items[0]
        row_index = currentTreeWidget.indexFromItem(selected_item).row()
        cite = self.resultSet[current_tab_index][1:][row_index]
        eid_val = cite['EID']
        pdf_name = '%s%s.pdf' % (self.config_dict['storageLocation'], eid_val)
        pdf_filename = QtGui.QFileDialog.getOpenFileName(self,
                                                         "Open the pdf file",
                                                         "",
                                                         "*.pdf")
        if pdf_filename == '':
            self.ui.statusbar.setText("An input file is needed")
            return
        shutil.copyfile(pdf_filename, pdf_name)
        f = pdf_downloader.convert_pdf_to_text(pdf_name, self.config_dict)
        while f: pass
        x = open('%s%s.txt' % (self.config_dict['storageLocation'], eid_val)).read()
        x = ' '.join(x.split())
        x = x.split('. ')
        x = '\n'.join(x)
        f = open('%s%s.txt' % (self.config_dict['storageLocation'], eid_val), 'w'); f.write(x); f.close()
        f = open('%s%s.dxt' % (self.config_dict['storageLocation'], eid_val), 'w'); f.write(repr(cite)); f.close()
        os.remove(pdf_name)
        if os.path.isfile('%s%s.txt' % (self.config_dict['storageLocation'], eid_val)):
                selected_item.setIcon(7, self.done_icon)
        self.ui.statusbar.clearMessage()
        self.ui.statusbar.showMessage('Records added')

    def downloadPdfFile(self):
        currentTreeWidget, current_tab_index = self.getTreeWidget_index()
        selected_items = currentTreeWidget.selectedItems()
        if len(selected_items) == 0:
            QtGui.QMessageBox.information (self, 'No Selection',
                                           'A record needs to be selected', QtGui.QMessageBox.Ok)
            return
        if len(selected_items) > 1:
            QtGui.QMessageBox.information (self, 'Multiple Selections',
                                           'Only one record can be selected for this process',
                                           QtGui.QMessageBox.Ok)
            return
        selected_item = selected_items[0]
        row_index = currentTreeWidget.indexFromItem(selected_item).row()
        lst = self.resultSet[current_tab_index][1:]
        cite = lst[row_index]
        try:
            detail = eval(open('%s%s.dxt' % (self.config_dict['storageLocation'], cite['EID'])).read())
        except:
            QtGui.QMessageBox.warning (self, 'Record not found.',
                                           'Works only for saved records. \
                                           Record for %s not found' % cite['Title'],
                                       QtGui.QMessageBox.Ok)
            return
        if not 'pdfLocation' in cite:
            t = pdf_downloader.PDFDownloadThread(self.config_dict)
            self.threadpool[self.threadCount] = t
            self.connect(self.threadpool[self.threadCount],
                         QtCore.SIGNAL("pdfLinkObtained"), self.save_pdf)
            self.threadpool[self.threadCount].start_process(row_index,
                                                            current_tab_index,
                                                            lst,
                                                            self.threadCount,
                                                            True)
            self.threadCount += 1
        else:
            self.save_pdf(cite)


    def save_pdf(self, citeItem):
        title = citeItem['Title']
        eid_val = citeItem['EID']
        pdf_link = citeItem['pdfLocation']
        if not pdf_link:
            QtGui.QMessageBox.warning (self, 'No pdf file.',
                                           'Cant get pdf for %s automatically.' % title,
                                       QtGui.QMessageBox.Ok)
            return
        pdf_filename = QtGui.QFileDialog.getSaveFileName(self,
                                                         "Save the pdf file for %s" % title,
                                                         "",
                                                         "*.pdf")
        pdf_filename = str(pdf_filename)
        if pdf_filename == '':
            self.ui.statusbar.setText("An input file is needed")
            return
        if not pdf_filename.endswith('.pdf'):
            pdf_filename = pdf_filename + '.pdf'
        self.save_pdf_to_location(pdf_link, pdf_filename, title, citeItem)

    def save_pdf_to_location(self, pdf_link, pdf_filename, title, cite_item):
        try:
            t = pdf_downloader.PDFSaveThread(self.config_dict, pdf_link, pdf_filename, cite_item, title)
            self.threadpool[self.threadCount] = t
            self.connect(self.threadpool[self.threadCount],
                     QtCore.SIGNAL('done'), self.done_saving_pdfs)
            self.connect(self.threadpool[self.threadCount],
                     QtCore.SIGNAL('error'), self.error_saving_pdfs)
            self.threadpool[self.threadCount].start_process()
            self.threadCount += 1
        except:
            QtGui.QMessageBox.warning (self, 'Error Saving.',
                                               'Pdf file for %s not saved' % title,
                                           QtGui.QMessageBox.Ok)
    def done_saving_pdfs(self, title):
        QtGui.QMessageBox.information (self, 'File saved.',
                                               'Pdf file for %s saved' % title,
                                           QtGui.QMessageBox.Ok)
    def error_saving_pdfs(self, title):
        QtGui.QMessageBox.warning (self, 'Error Saving.',
                                               'Pdf file for %s not saved' % title,
                                           QtGui.QMessageBox.Ok)
        
    def treeWidgetSized(self, treeWidget):
        treeWidget.header().resizeSection(0, 300)
        treeWidget.header().setResizeMode(0, QtGui.QHeaderView.Interactive)
        for i in range(1,6):
            treeWidget.header().resizeSection(i, 60)
            treeWidget.header().setResizeMode(i, QtGui.QHeaderView.Interactive)
            
    def test(self):
        reload(pdf_downloader)
        reload(reference_retrieve)

    def aboutCitationControl(self):
        QtGui.QMessageBox.about(self, "About Citation Control", """
        Citation Control v1.0 beta
        Copyright (c) Ajith Warrier
        Released: 30 September 2010.
        """)

    def open_preferences(self):
        self.window = QtGui.QDialog(self)
        self.pref = Ui_PreferencesDialog()
        self.pref.setupUi(self.window)
        self.pref.proxySitePwd.setEchoMode(2)
        self.pref.tabWidget.setTabText(0, 'Connection settings')
        self.pref.tabWidget.setTabText(1, 'Storage')
        self.pref.tabWidget.setTabText(2, 'PDF options')
        self.bBox_ids = {1 : self.pref.tagFullPath,
                         2 : self.pref.tagDir,
                         3 : self.pref.tagNone,
                         4 : self.pref.tagCustom}
        self.bBox = QtGui.QButtonGroup(self)
        for key in self.bBox_ids:
            self.bBox.addButton(self.bBox_ids[key], key)
        self.connect(self.pref.displCharactersCheckBox, QtCore.SIGNAL('stateChanged (int)'),
                     self.display_characters)
        self.connect(self.pref.radioButtonYesProxy, QtCore.SIGNAL('toggled(bool)'),
                     self.proxy_situation)
        self.connect(self.pref.radioButtonNoProxy, QtCore.SIGNAL('toggled(bool)'),
                     self.non_proxy_situation)
        self.connect(self.pref.buttonBox, QtCore.SIGNAL('accepted()'),
                     self.change_preferences)
        self.connect(self.pref.buttonBox, QtCore.SIGNAL('rejected()'),
                     self.dont_change_preferences)
        self.connect(self.pref.default_reset, QtCore.SIGNAL('clicked()'),
                     self.reset_to_default)
        self.connect(self.pref.browseStorageFolder, QtCore.SIGNAL('clicked()'),
                     self.search_for_storage_folder)
        config_dict = {}
        self.populate_configuration('../CitationControl.conf', config_dict)
        self.enter_preferences(config_dict)
        self.window.show()

    def search_for_storage_folder(self):
        directory = QtGui.QFileDialog.getExistingDirectory(self, 'Select Location for storage.')
        if directory == '':
            QtGui.QMessageBox.warning (self, 'An output folder is needed',
                                           'The temporary output folder will be delete \
                                           when you uninstall this program.',
                                           QtGui.QMessageBox.Ok)
            self.search_for_storage_folder()
        self.pref.storageFolderLocation.setText(str(directory) + os.sep)
        
    
    def display_characters(self, checkState):
        if checkState == 2:
            self.pref.proxySitePwd.setEchoMode(0)
        else:
            self.pref.proxySitePwd.setEchoMode(2)
            
    def proxy_situation(self, toggledSituation):
        self.pref.radioButtonNoProxy.setDown(False)
        self.pref.radioButtonYesProxy.setDown(True)
        self.pref.proxySiteLineEdit.setReadOnly(False)
        self.pref.proxySiteUsername.setReadOnly(False)
        self.pref.proxySitePwd.setReadOnly(False)
        self.pref.proxySiteLineEdit.setStyleSheet("QLineEdit { color: black;}")
        self.pref.proxySiteUsername.setStyleSheet("QLineEdit { color: black;}")
        self.pref.proxySitePwd.setStyleSheet("QLineEdit { color: black;}")
    
    def non_proxy_situation(self, toggledSituation):
        self.pref.radioButtonNoProxy.setDown(True)
        self.pref.radioButtonYesProxy.setDown(False)
        self.pref.proxySiteLineEdit.setReadOnly(True)
        self.pref.proxySiteUsername.setReadOnly(True)
        self.pref.proxySiteLineEdit.setStyleSheet("QLineEdit { color: lightgray;}")
        self.pref.proxySiteUsername.setStyleSheet("QLineEdit { color: lightgray;}")
        self.pref.proxySitePwd.setStyleSheet("QLineEdit { color: lightgray;}")
        self.pref.proxySitePwd.setReadOnly(True)

    def change_preferences(self):
        if self.pref.radioButtonNoProxy.isChecked():
            proxyreqd = 'No'
        elif self.pref.radioButtonNoProxy.isDown():
            proxyreqd = 'No'
        else:
            proxyreqd = 'Yes'
            
        if self.pref.savePdfsCheck.isChecked():
            pdfs_check = 'Yes'
        else:
            pdfs_check = 'No'

        if self.pref.allowDblClckPdfs.isChecked():
            dblClickedAllowed = 'Yes'
        else:
            dblClickedAllowed = 'No'

        if self.pref.markDuplicates.isChecked():
            dup_mark = 'Yes'
        elif self.pref.markDuplicates.isDown():
            dup_mark = 'Yes'
        else:
            dup_mark = 'No'
        checkName = self.bBox.checkedId()
        tag_name = self.bBox_ids[checkName].objectName()
        tag_text = self.pref.tagCustomEdt.text()
        if tag_text == '':
            tag_text = 'None'
        pwd = str(self.pref.proxySitePwd.text())
        username = self.pref.proxySiteUsername.text()
        proxysite = self.pref.proxySiteLineEdit.text()
        storageLocation = self.pref.storageFolderLocation.text()
        output_text = ["# Fill out the following details. Until a dialog is written, this",
                       "# information needs to be entered manually.",
                       "# All lines starting with # will be ignored.",
                       "# This file will be automatically updated during the next run.",
                       "proxyrequired %s" % proxyreqd,
                       "proxysite     %s" % proxysite,
                       "username      %s" % username,
                       " ",
                       "# For windows OSes, there needs to be an xpdf folder downloaded in the below location",
                       "pdfToTextLocation   pdftotext",
                       "iconLocation	    icons/" ,
                       "# The storage location",
                       " ",                       
                       "storageLocation	%s" % storageLocation,
                       "# Should pdfs be saved",
                       "savePdfsCheck  %s" % pdfs_check,
                       "# Allow double click to open pdfs",
                       "allowDblClckPdfs %s" % dblClickedAllowed,
                       "# Mark duplicates, if this value is set as No, then original records and pdfs will be overwritten with the newest duplicates.",
                       "markDuplicates %s" % dup_mark,
                       "# Decision on tags during indexing of pdfs",
                       "tags_value	%s" % tag_name,
                       "tags_text	%s" % tag_text]
        output_text = '\n'.join(output_text)
        f = open('../CitationControl.conf', 'w'); f.write(output_text); f.close()
        import bz2
        compressVal = '"%s"' % bz2.compress(pwd)
        f = open('adt', 'w'); f.write(compressVal); f.close()
        self.ui.statusbar.clearMessage()
        self.ui.statusbar.showMessage('Preferences changed', 2000)
        QtGui.QMessageBox.information (self, 'Restart CitationControl',
                                           'For changes to take effect, restart CitationControl',
                                       QtGui.QMessageBox.Ok)

    def dont_change_preferences(self):
        '''
        If the Preferences dialog is canceled.
        '''
        
        self.ui.statusbar.clearMessage()
        self.ui.statusbar.showMessage('Preferences not changed', 2000)

    def reset_to_default(self):
        '''
        Read the default configuration when the button is pressed.
        '''
        config_dict = {}
        self.populate_configuration('../CitationControl_default.conf', config_dict)
        self.enter_preferences(config_dict)

    def populate_configuration(self, conf_file, output_dict):
        '''
        A utility function to copy the configuration to a file.
        '''
        
        configText = open(conf_file).readlines()
        try:
            x = open('adt').read()
            x = x[1:-1]
            import bz2
            x = bz2.decompress(x)
            output_dict['password'] = x
        except:
            output_dict['password'] = ''
        if sys.platform == "win32":
            output_dict['pdfToTextLocation'] = 'xpdf\pdftotext.exe'
        else:
            output_dict['pdfToTextLocation'] = 'pdftotext'
        configText = [x for x in configText if not x.startswith('#')]
        for i in configText:
            if not i.strip() == '':
                vals = i.split()
                header = vals[0].strip(); value = vals[1].strip()
                output_dict[header] = value
        storageLoc = output_dict['storageLocation']
        if not os.path.isdir(storageLoc):
            os.mkdir(storageLoc)
                
    def enter_preferences(self, config_dict):
        '''
        A utility function to enter preferences into the preferences dialog.
        '''
        if config_dict['proxyrequired'] == 'No':
            self.non_proxy_situation(True)
        if config_dict['proxyrequired'] == 'Yes':
            self.proxy_situation(True)
        self.pref.proxySiteLineEdit.setText(config_dict['proxysite'])
        if not config_dict['tags_text'] == 'None':
            self.pref.tagCustomEdt.setText(config_dict['tags_text'])
        self.pref.proxySiteUsername.setText(config_dict['username'])
        self.pref.proxySitePwd.setText(config_dict['password'])
        self.pref.storageFolderLocation.setText(config_dict['storageLocation'])
        if config_dict['savePdfsCheck'] == 'Yes':
            self.pref.savePdfsCheck.setChecked(True)
        else:
            self.pref.savePdfsCheck.setChecked(False)

        if config_dict['allowDblClckPdfs'] == 'Yes':
            self.pref.allowDblClckPdfs.setChecked(True)
        else:
            self.pref.allowDblClckPdfs.setChecked(False)

        if config_dict['markDuplicates'] == 'Yes':
            self.pref.markDuplicates.setChecked(True)
        else:
            self.pref.overwrtDuplicates.setChecked(True)

        tag_button = config_dict['tags_value']
        tag_button = eval('self.pref.' + tag_button)
        tag_button.setChecked(True)
        

    def index_local_pdfs(self):
        self.search_widg = None
        self.extracted_pdf_list = []
        from pdf_index import IndexWindow
        self.window2 = IndexWindow(self)
        self.connect(self.window2, QtCore.SIGNAL('windowClosed'), self.index_window_closed)
        self.indexD = Ui_IndexingDialog()
        self.indexD.setupUi(self.window2)
        self.connect(self.indexD.entire_computer_button, QtCore.SIGNAL('clicked()'),
                     self.index_all_pdfs)
        self.connect(self.indexD.folder_choice_button, QtCore.SIGNAL('clicked()'),
                     self.index_folder_pdfs)
        self.connect(self.indexD.buttonBox, QtCore.SIGNAL('accepted()'),
                     self.index_window_closed)
        self.connect(self.indexD.buttonBox, QtCore.SIGNAL('rejected()'),
                     self.index_window_closed)
        # self.connect(self.indexD.folder_choice_button, QtCore.SIGNAL('closeEvent()'),
        #              self.close_indexing_window)
        self.window2.show()

    def index_window_closed(self):
        if self.search_widg:
            self.search_widg.running = False
        self.get_downloaded_file_info()
    
    def index_all_pdfs(self):
        if self.search_widg:
            self.search_widg.running = False
        reply = QtGui.QMessageBox.question(self, 'Entire Computer?',
                                           """This can take a long time!\nEvery pdf in your computer will be tested.\nThis includes non article pdfs as well.\nIf you have a lot of pdfs, this might take the time equivalent of defragmenting your computer.\nYou can, however, quit at any time.\n\n Are you sure you want to continue?""",
                                           QtGui.QMessageBox.Yes,
                                           QtGui.QMessageBox.No)
        if not reply == QtGui.QMessageBox.Yes:
            return
        directory = common_tools.get_root_folder()
        self.run_indexing(directory)

    def index_folder_pdfs(self):
        if self.search_widg:
            self.search_widg.running = False
        directory = QtGui.QFileDialog.getExistingDirectory(self, 'Select folder with stored pdfs.')
        if directory == '':
            return
        self.run_indexing(str(directory))
        
    def run_indexing(self, directory):
        import datetime
        timeN = datetime.datetime.now()
        from pdf_index import PDFIndexingThread       
        self.search_widg = PDFIndexingThread(str(directory), self.config_dict, timeN)
        self.connect(self.search_widg, QtCore.SIGNAL('pdf_file'),
                     self.updateExtracted)
        self.connect(self.search_widg, QtCore.SIGNAL('no_pdf_file'),
                     self.updateError)
        self.connect(self.search_widg, QtCore.SIGNAL('dup_pdf_file'),
                     self.updateDuplicates)
        self.search_widg.start_process()
        
    def updateExtracted(self, appendVal):
        '''
        When a pdf can be converted,
        then insert into the right box.
        '''        
        update_val = appendVal
        self.indexD.extractedPdfs.moveCursor(QtGui.QTextCursor.End, 1)
        self.indexD.extractedPdfs.insertHtml(update_val)

    def updateError(self, appendVal): 
        '''
        When a pdf cannot be converted,
        then insert into the error box.
        '''
        update_val = appendVal
        self.indexD.errorPdfs.moveCursor(QtGui.QTextCursor.End, 1)        
        self.indexD.errorPdfs.insertHtml(update_val)

    def updateDuplicates(self, appendVal):
        '''
        When a pdf cannot be converted,
        then insert into the error box.
        '''
        update_val = appendVal
        self.indexD.duplicatePdfs.moveCursor(QtGui.QTextCursor.End, 1)        
        self.indexD.duplicatePdfs.insertHtml(update_val)

    def item_double_clicked(self, item):
        currentTreeWidget, current_tab_index = self.getTreeWidget_index()
        selected_items = currentTreeWidget.selectedItems()
        if len(selected_items) == 0:
            QtGui.QMessageBox.information (self, 'No Selection',
                                           'A record needs to be selected', QtGui.QMessageBox.Ok)
            return
        if len(selected_items) > 1:
            QtGui.QMessageBox.information (self, 'Multiple Selections',
                                           'Only one record can be selected for this process',
                                           QtGui.QMessageBox.Ok)
            return
        selected_item = selected_items[0]
        row_index = currentTreeWidget.indexFromItem(selected_item).row()
        lst = self.resultSet[current_tab_index][1:]
        cite = lst[row_index]
        try:
            pdf_name = '%s%s.pdf' % (self.config_dict['storageLocation'], cite['EID'])
            if not os.path.isfile(pdf_name): raise
            if sys.platform == "win32":
                osFunc = 'start'
            else:
                osFunc = 'acroread'
            osFunc = '%s %s &' % (osFunc, pdf_name)
            os.popen(osFunc)
        except:
            QtGui.QMessageBox.warning (self, 'Record not found.',
                                           'Works only for saved records. Record for "%s" not found. Try obtaining this pdf again.' % cite['Title'],
                                       QtGui.QMessageBox.Ok)
            return

    def on_start_freeze(self):
        if self.prog_window.isHidden():
            self.prog_window.show()

    def on_end_freeze(self):
        if not self.prog_window.isHidden():
            self.prog_window.hide()

    def extract_images(self):
        currentTreeWidget, current_tab_index = self.getTreeWidget_index()
        selected_items = currentTreeWidget.selectedItems()
        if len(selected_items) == 0:
            QtGui.QMessageBox.information (self, 'No Selection',
                                           'A record needs to be selected', QtGui.QMessageBox.Ok)
            return
        if len(selected_items) > 1:
            QtGui.QMessageBox.information (self, 'Multiple Selections',
                                           'Only one record can be selected for this process',
                                           QtGui.QMessageBox.Ok)
            return
        selected_item = selected_items[0]
        row_index = currentTreeWidget.indexFromItem(selected_item).row()
        lst = self.resultSet[current_tab_index][1:]
        cite = lst[row_index]
        tempdir = self.config_dict['storageLocation'] + 'temp/'
        if not os.path.isdir(tempdir):
            os.mkdir(tempdir)
        pdf_name = '%s%s.pdf' % (self.config_dict['storageLocation'], cite['EID'])
        new_pdf_name = '%s%s.pdf' % (tempdir, cite['EID'])
        if os.path.isfile(pdf_name):
            self.img_window.show()
            shutil.copyfile(pdf_name, new_pdf_name)
        else:
            QtGui.QMessageBox.information (self, 'Pdf file not found',
                                           'Check "save pdfs" in preferences if you need this function. Then reload the searchable text for this file.',
                                           QtGui.QMessageBox.Ok)
            return
        if sys.platform == "win32":
            osFunc = 'xpdf\pdfimages.exe'
        else:
            osFunc = 'pdfimages'
        
        osFunc = "%s -j %s '%sFigure'" % (osFunc, new_pdf_name, tempdir)
        f = os.system(osFunc)
        while f: pass
        os.remove(new_pdf_name)
        from picture_viewer import PictureViewer
        self.pv = PictureViewer(tempdir, self)
        self.pv.showMaximized()
        self.img_window.hide()

    def closeEvent(self, event):
        self.threadCount = 0
        self.threadpool = {}
        self.pdf_download_pool = []
        self.current_pdf_threads = []
        self.done_threads = 0
        self.started_threads = 0
        self.threads_done = True
        
        
if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    myapp = StartQT4()
    myapp.showMaximized()
    sys.exit(app.exec_())
